#include <iostream>
#include <unistd.h>
#include <pthread.h>

// 线程终止和线程分离

// 只有线程终止而进程不终止有三种方法
// 1.从线程函数return。这种方法对主线程不适用，从main函数return相当于调用exit。
// 2.线程可以调用pthread_exit终止自己。
// 3.其他线程可以调用 pthread_cancel 终止同一进程中的另一个线程。

void *rutine1(void *args)
{
    std::string name = static_cast<const char *>(args);
    std::cout << name << "退出,返回值为10 " << std::endl;
    pthread_exit((void *)10);
}
void *rutine2(void *args)
{
    std::string name = static_cast<const char *>(args);
    while (true)
    {
        std::cout << name << "线程运行中" << std::endl;
        sleep(1);
    }
    return nullptr;
}
void *rutine3(void *args)
{
    //线程自己分离自己
    pthread_detach(pthread_self());
    std::string name = static_cast<const char *>(args);
    while(true)
    {
        std::cout<<name<<"线程运行中"<<std::endl;
        sleep(3);
    }
    return nullptr;
}

int main()
{
    pthread_t th1, th2, th3;
    pthread_create(&th1, nullptr, rutine1, (void *)"thread-1");
    void *ret = nullptr;
    int n1=pthread_join(th1, &ret);
    std::cout <<"n1:"<<n1<< " 线程等待成功,返回值为" << (long long int)ret << std::endl;

    sleep(5);

    pthread_create(&th2, nullptr, rutine2, (void *)"thread-2");
    sleep(5);
    std::cout << "main线程将终止thread-2" << std::endl;
    pthread_cancel(th2);
    int n2=pthread_join(th2, &ret);
    // 一个线程被取消之后，ret = -1，线程的退出码是 PTHREAD_CANCELD
    std::cout <<"n2:"<<n2<< " 线程等待成功,返回值为:" << (long long int)ret << std::endl;

    sleep(5);
    // 1.默认情况下，新创建的线程是joinable的，线程退出后，需要对其进行pthread_join操作，否则无法释放资源，从而造成系统泄漏
    // 2.如果不关心线程的返回值，join是一种负担，这个时候，我们可以告诉系统，当线程退出时，自动释放线程资源
    // 3.joinable和分离是冲突的，一个线程不能既是joinable又是分离的。
    // 4.如果一个线程被分离，线程的工作状态就是分离状态，不需要被join，但依旧属于进程内部
    //5.线程既可以自己进行分离也可以由main线程进行分离
    pthread_create(&th3, nullptr, rutine3, (void *)"thread-3");
    //pthread_detach(tid); // 主线程对指定线程做分离
    sleep(1);
    int n3=pthread_join(th3,&ret);
    std::cout <<"n3:"<<n3<< "ret:" << (long long int)ret << std::endl;
    sleep(5);
    //注意多线程中,主线程是最后退出的,主线程退出后,分离的th3也会退出
    return 0;
}